#include "server.hpp"
//客户端不显示绑定端口号，ip会自带
#define Printfd "/dev/pts/1"

struct serverData
{
    serverData(const sockaddr_in &server, const int &sockfp)
    :server_(server), sockfp_(sockfp)
    {}

    ~serverData()
    {}

    sockaddr_in server_; //包含了服务端的ip和端口号
    int sockfp_;      //套接字
};
void* reading(void* args)
{
    serverData* sp = static_cast<serverData*>(args);
    int fd = open(Printfd, O_WRONLY|O_TRUNC);
    if(fd < 0)
    {
        lg(Fatal, "客户端读文件打开失败: %s, errno: %d", strerror(errno), errno);
        exit(ERROR_READFP);
    }
    socklen_t len = sizeof(sp->server_);
    char* buffer[1024];
    while(true)
    {
        int n = recvfrom(sp->sockfp_, buffer, sizeof(buffer), 0, (sockaddr*)&sp->server_, &len);
        if(n < 0)
        {
            lg(Warning, "读取服务端的通知失败: %s, errno: %d", strerror(errno), errno);
            exit(ERROR_REVEFROM_SERVER);
        }
        buffer[n] = 0;
        write(fd, buffer, n);
    }
    
    //dup2(fd, 2); //2对应的文件是标准错误文件，属于显示屏文件
}

void* sending(void* args)
{
    serverData* sp = static_cast<serverData*>(args);
    socklen_t len = sizeof(sp->server_);
    std::string messages;
    while(true)
    {
        std::getline(std::cin, messages);
        messages += "\n";
        sendto(sp->sockfp_, messages.c_str(), messages.size(), 0, (const sockaddr*)&sp->server_, len);
    }
}

int main(int argv, char* args[])
{
    if(argv != 3)
    {
        perror("客户端启动失败,请使用 ./cilent IP PORT 的方式启动");
        exit(OPEN_CILENT);
    }
    int sockfp = socket(AF_INET, SOCK_DGRAM, 0);
    std::string ip = args[1];           //要发送的服务端的IP地址
    uint16_t port = stoi(args[2]);      //要发送的服务端的端口号

    struct sockaddr_in server;
    bzero(&server, sizeof(server));
    server.sin_addr.s_addr =inet_addr(ip.c_str());
    server.sin_port = htons(port);
    //要发送的服务端的数据结构体server已经准备完成

    serverData dt(server, sockfp);  //dt是给每个线程的结构体，里面保存了发送目标的数据结构体
    pthread_t Read, Send;   //一个负责读，一个负责写

    pthread_create(&Read, nullptr, reading, (void*)&dt);
    pthread_create(&Send, nullptr, sending, (void*)&dt);
    
    
    pthread_join(Read, nullptr);
    pthread_join(Send, nullptr);
    return 0;
}